package org.dslintegration.serializer;

import com.google.inject.Inject;
import com.google.inject.Provider;
import org.dslintegration.mRules.Expression;
import org.dslintegration.mRules.LeftAttribute;
import org.dslintegration.mRules.MRulesPackage;
import org.dslintegration.mRules.MergeRules;
import org.dslintegration.mRules.Output;
import org.dslintegration.mRules.RightAttribute;
import org.dslintegration.mRules.Rule;
import org.dslintegration.mRules.RuleStatement;
import org.dslintegration.mRules.Source;
import org.dslintegration.mRules.Target;
import org.dslintegration.services.MRulesGrammarAccess;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
import org.eclipse.xtext.serializer.sequencer.ISemanticNodeProvider.INodesForEObjectProvider;
import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;

@SuppressWarnings("restriction")
public class AbstractMRulesSemanticSequencer extends AbstractSemanticSequencer {

	@Inject
	protected MRulesGrammarAccess grammarAccess;
	
	@Inject
	protected ISemanticSequencerDiagnosticProvider diagnosticProvider;
	
	@Inject
	protected ITransientValueService transientValues;
	
	@Inject
	@GenericSequencer
	protected Provider<ISemanticSequencer> genericSequencerProvider;
	
	protected ISemanticSequencer genericSequencer;
	
	
	@Override
	public void init(ISemanticSequencer sequencer, ISemanticSequenceAcceptor sequenceAcceptor, Acceptor errorAcceptor) {
		super.init(sequencer, sequenceAcceptor, errorAcceptor);
		this.genericSequencer = genericSequencerProvider.get();
		this.genericSequencer.init(sequencer, sequenceAcceptor, errorAcceptor);
	}
	
	public void createSequence(EObject context, EObject semanticObject) {
		if(semanticObject.eClass().getEPackage() == MRulesPackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
			case MRulesPackage.EXPRESSION:
				if(context == grammarAccess.getExpressionRule()) {
					sequence_Expression(context, (Expression) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.LEFT_ATTRIBUTE:
				if(context == grammarAccess.getLeftAttributeRule()) {
					sequence_LeftAttribute(context, (LeftAttribute) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.MERGE_RULES:
				if(context == grammarAccess.getMergeRulesRule()) {
					sequence_MergeRules(context, (MergeRules) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.OUTPUT:
				if(context == grammarAccess.getOutputRule()) {
					sequence_Output(context, (Output) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.RIGHT_ATTRIBUTE:
				if(context == grammarAccess.getRightAttributeRule()) {
					sequence_RightAttribute(context, (RightAttribute) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.RULE:
				if(context == grammarAccess.getRuleRule()) {
					sequence_Rule(context, (Rule) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.RULE_STATEMENT:
				if(context == grammarAccess.getRuleStatementRule()) {
					sequence_RuleStatement(context, (RuleStatement) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.SOURCE:
				if(context == grammarAccess.getSourceRule()) {
					sequence_Source(context, (Source) semanticObject); 
					return; 
				}
				else break;
			case MRulesPackage.TARGET:
				if(context == grammarAccess.getTargetRule()) {
					sequence_Target(context, (Target) semanticObject); 
					return; 
				}
				else break;
			}
		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
	}
	
	/**
	 * Constraint:
	 *     (left+=LeftAttribute left+=LeftAttribute* right+=RightAttribute right+=RightAttribute*)
	 *
	 * Features:
	 *    left[1, *]
	 *    right[1, *]
	 */
	protected void sequence_Expression(EObject context, Expression semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (source=[Source|ID] attributeName=ID)
	 *
	 * Features:
	 *    source[1, 1]
	 *    attributeName[1, 1]
	 */
	protected void sequence_LeftAttribute(EObject context, LeftAttribute semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, MRulesPackage.Literals.LEFT_ATTRIBUTE__SOURCE) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, MRulesPackage.Literals.LEFT_ATTRIBUTE__SOURCE));
			if(transientValues.isValueTransient(semanticObject, MRulesPackage.Literals.LEFT_ATTRIBUTE__ATTRIBUTE_NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, MRulesPackage.Literals.LEFT_ATTRIBUTE__ATTRIBUTE_NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getLeftAttributeAccess().getSourceSourceIDTerminalRuleCall_0_0_1(), semanticObject.getSource());
		feeder.accept(grammarAccess.getLeftAttributeAccess().getAttributeNameIDTerminalRuleCall_2_0(), semanticObject.getAttributeName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     (metamodelPathLeft=STRING metamodelPathRight=STRING defaultDominant='default dominant '? rules+=Rule+)
	 *
	 * Features:
	 *    metamodelPathLeft[1, 1]
	 *    metamodelPathRight[1, 1]
	 *    defaultDominant[0, 1]
	 *    rules[1, *]
	 */
	protected void sequence_MergeRules(EObject context, MergeRules semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (create?='create'? qualifiedName=QName name=ID)
	 *
	 * Features:
	 *    create[0, 1]
	 *    qualifiedName[1, 1]
	 *    name[1, 1]
	 */
	protected void sequence_Output(EObject context, Output semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (target=[Target|ID] attributeName=ID)
	 *
	 * Features:
	 *    target[1, 1]
	 *    attributeName[1, 1]
	 */
	protected void sequence_RightAttribute(EObject context, RightAttribute semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, MRulesPackage.Literals.RIGHT_ATTRIBUTE__TARGET) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, MRulesPackage.Literals.RIGHT_ATTRIBUTE__TARGET));
			if(transientValues.isValueTransient(semanticObject, MRulesPackage.Literals.RIGHT_ATTRIBUTE__ATTRIBUTE_NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, MRulesPackage.Literals.RIGHT_ATTRIBUTE__ATTRIBUTE_NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getRightAttributeAccess().getTargetTargetIDTerminalRuleCall_0_0_1(), semanticObject.getTarget());
		feeder.accept(grammarAccess.getRightAttributeAccess().getAttributeNameIDTerminalRuleCall_2_0(), semanticObject.getAttributeName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     (statement=ID expession=Expression (output=[Output|ID] outputAttribute=ID)?)
	 *
	 * Features:
	 *    statement[1, 1]
	 *    expession[1, 1]
	 *    output[0, 1]
	 *         EXCLUDE_IF_UNSET outputAttribute
	 *         MANDATORY_IF_SET outputAttribute
	 *    outputAttribute[0, 1]
	 *         EXCLUDE_IF_UNSET output
	 *         MANDATORY_IF_SET output
	 */
	protected void sequence_RuleStatement(EObject context, RuleStatement semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (ruleName=ID source=Source target=Target output=Output? statements+=RuleStatement*)
	 *
	 * Features:
	 *    ruleName[1, 1]
	 *    source[1, 1]
	 *    target[1, 1]
	 *    output[0, 1]
	 *    statements[0, *]
	 */
	protected void sequence_Rule(EObject context, Rule semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (dominant?='dominant'? guard?='guard'? qualifiedName=QName name=ID)
	 *
	 * Features:
	 *    dominant[0, 1]
	 *    guard[0, 1]
	 *    qualifiedName[1, 1]
	 *    name[1, 1]
	 */
	protected void sequence_Source(EObject context, Source semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (dominant?='dominant'? guard?='guard'? qualifiedName=QName name=ID)
	 *
	 * Features:
	 *    dominant[0, 1]
	 *    guard[0, 1]
	 *    qualifiedName[1, 1]
	 *    name[1, 1]
	 */
	protected void sequence_Target(EObject context, Target semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
}
